home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part2 / 14753 < prev    next >
Encoding:
Text File  |  1996-08-05  |  5.6 KB  |  151 lines

  1. Path: news.compuserve.com!newsmaster
  2. From: Philippe Verdy <100105.3120@compuserve.com>
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: Help: Can't extract fractional digits of DOUBLE
  5. Date: 1 Apr 1996 23:35:40 GMT
  6. Organization: CompuServe Incorporated
  7. Message-ID: <4jpp8c$lhj@dub-news-svc-6.compuserve.com>
  8. NNTP-Posting-Host: ad15-078.compuserve.com
  9.  
  10. Simon Lee (Simon Lee) s'Θcrit :
  11. > Hello everyone,
  12. > I'm trying to take a double value and extract each digit from the value.
  13. > The way I'm doing it is:
  14. > double number = somevalue;
  15. > 1 while(number != 0)
  16. > 2 {
  17. > 3    m_cpTerm[i] = (char)(number*10) % 10;
  18. > 4    number = (double)(number - (char)number) * 10.0;
  19. > 5
  20. > 6    precision++;
  21. > 7
  22. > 8    // Stop and round up if we've reached the end of double's precision.
  23. > 9    if (precision == DOUBLE_PREC)
  24. > 10    {
  25. > 11        if (((long)(number*10.0)%10) >= 5)
  26. > 12        {
  27. > 13            m_cpTerm[i] += 1;
  28. > 14        }
  29. > 15        break;
  30. > 16    }
  31. > 17
  32. > 18    i++;
  33. > 19 }
  34. > Suppose number = 2.34.
  35. > What happens is after I get the last digit (4), it does line 4, and then
  36. > number = 9.99999999999, or if number was a longer value like 1.23458724,
  37. > after about 4 or 5 shifts to the left, random value starts appearing at 
  38. > the end of the precision.  Thus it never exits the while loop unless it
  39. > satisfies line 9.
  40. > Anyone know of a solution to this problem?
  41. > BTW. I'm creating an arbitrary precision class, and this is used to convert
  42. > a double to the class.
  43. > Please email any info or help.
  44. > Thank you,
  45. > Simon Lee
  46. > P.S.  Anyone know of a fast and simple algorithm to do
  47. > division?
  48.  
  49. Floating point numbers on most machines are not stored in a 
  50. 10 radix, but use a binary radix, i.e. numbers are internally
  51. stored on the following form:
  52. sign * mantissa * 2 ^ exponent,
  53. with a constraint like: mantissa between [0.5, 1[,
  54. and sign in {-1; +1}, and exponent as a positive or negative
  55. integer.
  56. For example, 1.5 = +1 * 0.75 * 2 ^ + 1
  57. - the sign is stored as a single bit
  58. - the mantissa is stored as an integer with a fixed number
  59. of bits, which value is the rounding of the mantissa,
  60. scaled to a power of 2 which is the number of bits.
  61. - the integral signed exponent is stored as an unsigned
  62. integer with a fixed number of bits, after adding it a constant
  63. value.
  64. Expressed that way, this is ewuivalent to storing the number
  65. with the form: sign * scaled_mantissa * 2 ^ (exponent-scaling)
  66. where scaled_mantissa and exponent are integers only,
  67. and scaling is the fixed bit width of the field which is used
  68. to store the precision of the mantissa.
  69.  
  70. Additionally, because of the constraint: mantissa in [0.5; 1[
  71. the unscaled_mantissa (expressed as a fixed bit-width integer)
  72. will always have its highest bit equal to 1. Then this bit
  73. does not need to be stored, and one additional bit is avai-
  74. lable for the precision, or this bit replaced by the sign bit.
  75. This property is used for storing 4-bytes floats, but not for
  76. 8-bytes doubles.
  77.  
  78. If you don't use this bit, you can specify special values
  79. like denormal numbers, NaNs (Not a Number values), and
  80. infinity(ies), by using mantissa which do not conform to the
  81. constraint, or by reserving one value of the exponent for
  82. that usage.
  83.  
  84. The IEEE commitee has defined standard definitions for
  85. portable float and double types, which should be used or
  86. recognized by most compilers (or by the way of a standard
  87. IEEE library): the fix the size in bits of each part, and
  88. the shiting value for the exponent, so that a number like
  89. 0.5 has a given exponent value part.
  90.  
  91. ----------------------- So what ? --------------------------
  92.  
  93. The problem you have is that the division by 10 you are using
  94. is not exact when applied on a number expressed in radix 2
  95. (you've got the same problem by dividing by 3 in the classic
  96. 10 radix). So once you have extracted a digit, the multiplica
  97. tion by 10, substracted from you original number does not give
  98. you the exact result you were expecting to.
  99.  
  100. This is the same problem which occurs when you would like to
  101. express 1.1 in with all its digits in a radix 3. You get the
  102. first digits (for the integral part) you have no problems,
  103. because integers are exact in all radixes.
  104. However this is not true for fractional numbers stored in
  105. floating point variables.
  106.  
  107. The problem is due to the limit of precision of the mantissa
  108. which has a fixed limited number of bits to express it.
  109. The more bits you have for the mantissa, the more precise
  110. you fractional number will be computed and stored.
  111.  
  112. Within <limits.h>, you will find ANSI definitions of your
  113. floating point numbers implementation, so that you can
  114. parameterize your implementation to avoid excess of precision
  115. (which would really mean excess of UNprecision).
  116. These limits are expressed in bits or in digits (of radix 10)
  117. and also define an epsilon value which is the most little
  118. fraction which can be added to 1, for which the result is
  119. different from 1. Do not mismatch them !!!
  120.  
  121. Don't forget also that the precision given by the mantissa
  122. is counting also the precision given by the integer part
  123. of your number:
  124.  
  125. If you write 2582.56, you have 6 digits of precision in
  126. the 10 radix, not 2 !
  127.  
  128. The same applies when using the 2 radix !!!
  129. 2582.56 is expressed as : +0.6305078125 * 4096, for which we
  130. could limit the mantissa to only 23 bits. So the most little
  131. bit of the mantissa would count for 1 / 2^23 =~= 1.19E-7 only,
  132. and the excess of precision of the previous long mantissa
  133. (the last "125" digits) is lost when storing the 2582.56
  134. number in such a float variable.
  135. So we will only store an approximation.
  136.  
  137. If we keep the 23 bits mantissa (classic value for floats)
  138. we can compute this rounded mantissa by first multiplying
  139. the mantissa by 2^23, i.e. by multiplying it by the power of 2
  140. which is (23 minus the magnitude of the number).
  141.  
  142.